#include "PS2.h"
#include "spi.h"

/*单片机向手柄发送命令或读数据
0x01起始命令 0x42请求数据 0x00空闲*/
uint8_t CMD[3] = { 0x01,0x42,0x00 };
/*一个通讯周期9字节(8位)	按下为0其余为1*/
uint8_t PS2OriginalValue[9] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
/*左右摇杆模拟值*/
uint8_t RockerValue[4] = { 0x00,0x00,0x00,0x00 };
/*16个按键的值
SELECT L3 R3 START UP RIGHT DOWN LEFT
L2 R2 L1 R1 triangle circle cross square*/
uint8_t ButtonValue[16] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
/*i用于遍历 mode手柄回复单片机ID
0x41绿灯模式 0x73红灯模式(可发送模拟值) 0x5A数据来了*/
uint8_t i,mode;

void Delay_us(uint32_t udelay)//微秒级延时
{
	uint32_t startval, tickn, delays, wait;

	startval = SysTick->VAL;// 获取当前 SysTick 计数器的值
	tickn = HAL_GetTick();// 获取当前的毫秒级系统时间
	delays = udelay * 72;// 计算需要的延时周期数（SysTick 的时钟频率为 72MHz，每周期约 13.89ns）
	if (delays > startval)// 判断延时周期数是否大于当前 SysTick 计数器的值
	{
		while (HAL_GetTick() == tickn)// 空循环，等待系统时间变化
		{

		}
		wait = 72000 + startval - delays;// 计算等待的 SysTick 值，确保延时足够长
		while (wait < SysTick->VAL) // 空循环，等待 SysTick 计数器达到目标值
		{

		}
	}
	else  // 如果延时周期数小于当前 SysTick 计数器的值
	{
		wait = startval - delays;  // 等待直到 SysTick 计数器的值超过计算的等待值，同时确保系统时间未变化
		while (wait < SysTick->VAL && HAL_GetTick() == tickn)   // 空循环，等待 SysTick 计数器达到目标值
		{

		}
	}
}

void PS2OriginalValueGet(void)//获取原始数据 
{
	short i = 0;

	HAL_GPIO_WritePin(CSS_GPIO_Port, CSS_Pin, GPIO_PIN_RESET); // 将CSS引脚拉低，开始通信
	/*单片机三个命令*/
	HAL_SPI_TransmitReceive(&hspi1, &CMD[0], &PS2OriginalValue[0], 1, HAL_MAX_DELAY);
	Delay_us(10);
	HAL_SPI_TransmitReceive(&hspi1, &CMD[1], &PS2OriginalValue[1], 1, HAL_MAX_DELAY);
	Delay_us(10);
	HAL_SPI_TransmitReceive(&hspi1, &CMD[2], &PS2OriginalValue[2], 1, HAL_MAX_DELAY);
	Delay_us(10);
	/*手柄012无数据返回 单片机发送完命令始终空闲*/
	for (i = 3; i < 9; i++)
	{
		HAL_SPI_TransmitReceive(&hspi1, &CMD[2], &PS2OriginalValue[i], 1, HAL_MAX_DELAY);
		Delay_us(10);
	}

	HAL_GPIO_WritePin(CSS_GPIO_Port, CSS_Pin, GPIO_PIN_SET);//将CSS引脚拉高，结束通信

}


void PS2AllValueUpdate(void)
{
	PS2OriginalValueGet();// 获取PS2控制器的原始数据
	RockerValueGet();// 更新摇杆值
	ButtonValueGet();// 更新按钮值
	mode = PS2OriginalValue[1];// 设置模式为PS2控制器的第二个字节
	PS2OriginalValueClear();// 清空PS2控制器的原始数据
}

void RockerValueGet(void)
{
	int i;
	for (i = 5; i < 9; i++) // 从PS2控制器的第6到第9个字节提取摇杆值
	{
		PS2OriginalValue[i] = (int)PS2OriginalValue[i];// 强制类型转换为int
		RockerValue[i - 5] = PS2OriginalValue[i];; // 存储到RockerValue数组
	}
}

void PS2OriginalValueClear(void)//清空PS2OriginalValue数组
{
	for (i = 0; i < 9; i++)
	{
		PS2OriginalValue[i] = 0x00; 
	}
}

void ButtonValueGet(void)//读取按钮值
{
	uint8_t bit = 1;
	uint8_t button = 0;
	/*1 << bit：将1左移bit位，生成一个掩码
	例：bit = 0 掩码为0x01；bit = 1 掩码为 0x02 
	PS2OriginalValue[3] & (1 << bit)  ：将   PS2OriginalValue[3]   与掩码进行按位与操作。
	PS2OriginalValue[3]   的第   bit   位为 1，则结果为   1 << bit  ；否则结果为 0。
	(PS2OriginalValue[3] & (1 << bit)) >> bit  ：将上述结果右移   bit   位
	如果第   bit   位为 1，则结果为 1；否则结果为 0。
	提取出了PS2OriginalValue[3]   的第   bit   位的值
	*/
	for (bit = 8; bit > 0; bit--)
	{
		bit -= 1;//0-7
		ButtonValue[button] = (PS2OriginalValue[3] & (1 << bit)) >> bit;
		bit += 1;//在提取完当前位后，将   bit   加 1，恢复到原来的值，以便下一次循环
		button++;//每次提取完一个位后，将   button   加 1，表示下一个按钮状态将存储到   ButtonValue   的下一个位置
	}
	/*简化
	for (bit = 7; bit >= 0; bit--) // 从第7位到第0位
	{
		ButtonValue[button] = (PS2OriginalValue[3] & (1 << bit)) >> bit; // 提取第bit位的值
		button++;
	}*/
	for (bit = 8; bit > 0; bit--)
	{
		bit -= 1;
		ButtonValue[button] = (PS2OriginalValue[4] & (1 << bit)) >> bit;
		bit += 1;
		button++;
	}
	for (button = 0; button < 16; button++) //取反
	{
		if (ButtonValue[button] == 1)  ButtonValue[button] = 0;
		else  ButtonValue[button] = 1;
	}
}

int PS2RedLight(void) // 如果模式为0x73，返回1（打开红灯）
{
	if (mode == 0X73)
		return 1;
	else
		return 0;
}
